home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / HTTP.php < prev    next >
Encoding:
PHP Script  |  2005-12-02  |  12.1 KB  |  360 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3.  
  4. /**
  5.  * HTTP
  6.  * 
  7.  * PHP versions 4 and 5
  8.  *
  9.  * @category    HTTP
  10.  * @package     HTTP
  11.  * @author      Stig Bakken <ssb@fast.no>
  12.  * @author      Sterling Hughes <sterling@php.net>
  13.  * @author      Tomas V.V.Cox <cox@idecnet.com>
  14.  * @author      Richard Heyes <richard@php.net>
  15.  * @author      Philippe Jausions <Philippe.Jausions@11abacus.com>
  16.  * @author      Michael Wallner <mike@php.net>
  17.  * @copyright   2002-2005 The Authors
  18.  * @license     BSD, revised
  19.  * @version     CVS: $Id: HTTP.php,v 1.48 2005/11/08 20:11:54 mike Exp $
  20.  * @link        http://pear.php.net/package/HTTP
  21.  */
  22.  
  23. /**
  24.  * Miscellaneous HTTP Utilities
  25.  *
  26.  * PEAR::HTTP provides static shorthand methods for generating HTTP dates,
  27.  * issueing HTTP HEAD requests, building absolute URIs, firing redirects and
  28.  * negotiating user preferred language.
  29.  *
  30.  * @package     HTTP
  31.  * @category    HTTP
  32.  * @access      public
  33.  * @static
  34.  * @version     $Revision: 1.48 $
  35.  */
  36. class HTTP
  37. {
  38.     /**
  39.      * Date
  40.      * 
  41.      * Format a RFC compliant GMT date HTTP header.  This function honors the 
  42.      * "y2k_compliance" php.ini directive and formats the GMT date corresponding
  43.      * to either RFC850 or RFC822.
  44.      * 
  45.      * @static 
  46.      * @access  public 
  47.      * @return  mixed   GMT date string, or false for an invalid $time parameter
  48.      * @param   mixed   $time unix timestamp or date (default = current time)
  49.      */
  50.     function Date($time = null)
  51.     {
  52.         if (!isset($time)) {
  53.             $time = time();
  54.         } elseif (!is_numeric($time) && (-1 === $time = strtotime($time))) {
  55.             return false;
  56.         }
  57.         
  58.         // RFC822 or RFC850
  59.         $format = ini_get('y2k_compliance') ? 'D, d M Y' : 'l, d-M-y';
  60.         
  61.         return gmdate($format .' H:i:s \G\M\T', $time);
  62.     }
  63.  
  64.     /**
  65.      * Negotiate Language
  66.      * 
  67.      * Negotiate language with the user's browser through the Accept-Language 
  68.      * HTTP header or the user's host address.  Language codes are generally in 
  69.      * the form "ll" for a language spoken in only one country, or "ll-CC" for a 
  70.      * language spoken in a particular country.  For example, U.S. English is 
  71.      * "en-US", while British English is "en-UK".  Portugese as spoken in
  72.      * Portugal is "pt-PT", while Brazilian Portugese is "pt-BR".
  73.      * 
  74.      * Quality factors in the Accept-Language: header are supported, e.g.:
  75.      *      Accept-Language: en-UK;q=0.7, en-US;q=0.6, no, dk;q=0.8
  76.      * 
  77.      * <code>
  78.      *  require_once 'HTTP.php';
  79.      *  $langs = array(
  80.      *      'en'   => 'locales/en',
  81.      *      'en-US'=> 'locales/en',
  82.      *      'en-UK'=> 'locales/en',
  83.      *      'de'   => 'locales/de',
  84.      *      'de-DE'=> 'locales/de',
  85.      *      'de-AT'=> 'locales/de',
  86.      *  );
  87.      *  $neg = HTTP::negotiateLanguage($langs);
  88.      *  $dir = $langs[$neg];
  89.      * </code>
  90.      * 
  91.      * @static 
  92.      * @access  public 
  93.      * @return  string  The negotiated language result or the supplied default.
  94.      * @param   array   $supported An associative array of supported languages,
  95.      *                  whose values must evaluate to true.
  96.      * @param   string  $default The default language to use if none is found.
  97.      */
  98.     function negotiateLanguage($supported, $default = 'en-US')
  99.     {
  100.         $supp = array();
  101.         foreach ($supported as $lang => $isSupported) {
  102.             if ($isSupported) {
  103.                 $supp[strToLower($lang)] = $lang;
  104.             }
  105.         }
  106.         
  107.         if (!count($supp)) {
  108.             return $default;
  109.         }
  110.  
  111.         $matches = array();
  112.         if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  113.             foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang) {
  114.                 $lang = array_map('trim', explode(';', $lang));
  115.                 if (isset($lang[1])) {
  116.                     $l = strtolower($lang[0]);
  117.                     $q = (float) str_replace('q=', '', $lang[1]);
  118.                 } else {
  119.                     $l = strtolower($lang[0]);
  120.                     $q = null;
  121.                 }
  122.                 if (isset($supp[$l])) {
  123.                     $matches[$l] = isset($q) ? $q : 1000 - count($matches);
  124.                 }
  125.             }
  126.         }
  127.  
  128.         if (count($matches)) {
  129.             asort($matches, SORT_NUMERIC);
  130.             return $supp[end($l = array_keys($matches))];
  131.         }
  132.         
  133.         if (isset($_SERVER['REMOTE_HOST'])) {
  134.             $lang = strtolower(end($h = explode('.', $_SERVER['REMOTE_HOST'])));
  135.             if (isset($supp[$lang])) {
  136.                 return $supp[$lang];
  137.             }
  138.         }
  139.  
  140.         return $default;
  141.     }
  142.  
  143.     /**
  144.      * Head
  145.      * 
  146.      * Sends a "HEAD" HTTP command to a server and returns the headers
  147.      * as an associative array. Example output could be:
  148.      * <code>
  149.      *     Array
  150.      *     (
  151.      *         [response_code] => 200          // The HTTP response code
  152.      *         [response] => HTTP/1.1 200 OK   // The full HTTP response string
  153.      *         [Date] => Fri, 11 Jan 2002 01:41:44 GMT
  154.      *         [Server] => Apache/1.3.20 (Unix) PHP/4.1.1
  155.      *         [X-Powered-By] => PHP/4.1.1
  156.      *         [Connection] => close
  157.      *         [Content-Type] => text/html
  158.      *     )
  159.      * </code>
  160.      * 
  161.      * @see HTTP_Client::head()
  162.      * @see HTTP_Request
  163.      * 
  164.      * @static 
  165.      * @access  public 
  166.      * @return  mixed   Returns associative array of response headers on success
  167.      *                  or PEAR error on failure.
  168.      * @param   string  $url A valid URL, e.g.: http://pear.php.net/credits.php
  169.      * @param   integer $timeout Timeout in seconds (default = 10)
  170.      */
  171.     function head($url, $timeout = 10)
  172.     {
  173.         $p = parse_url($url);
  174.         if (!isset($p['scheme'])) {
  175.             $p = parse_url(HTTP::absoluteURI($url));
  176.         } elseif ($p['scheme'] != 'http') {
  177.             return HTTP::raiseError('Unsupported protocol: '. $p['scheme']);
  178.         }
  179.  
  180.         $port = isset($p['port']) ? $p['port'] : 80;
  181.  
  182.         if (!$fp = @fsockopen($p['host'], $port, $eno, $estr, $timeout)) {
  183.             return HTTP::raiseError("Connection error: $estr ($eno)");
  184.         }
  185.  
  186.         $path  = !empty($p['path']) ? $p['path'] : '/';
  187.         $path .= !empty($p['query']) ? '?' . $p['query'] : '';
  188.  
  189.         fputs($fp, "HEAD $path HTTP/1.0\r\n");
  190.         fputs($fp, 'Host: ' . $p['host'] . ':' . $port . "\r\n");
  191.         fputs($fp, "Connection: close\r\n\r\n");
  192.  
  193.         $response = rtrim(fgets($fp, 4096));
  194.         if (preg_match("|^HTTP/[^\s]*\s(.*?)\s|", $response, $status)) {
  195.             $headers['response_code'] = $status[1];
  196.         }
  197.         $headers['response'] = $response;
  198.  
  199.         while ($line = fgets($fp, 4096)) {
  200.             if (!trim($line)) {
  201.                 break;
  202.             }
  203.             if (($pos = strpos($line, ':')) !== false) {
  204.                 $header = substr($line, 0, $pos);
  205.                 $value  = trim(substr($line, $pos + 1));
  206.                 $headers[$header] = $value;
  207.             }
  208.         }
  209.         fclose($fp);
  210.         return $headers;
  211.     }
  212.  
  213.     /**
  214.      * Redirect
  215.      * 
  216.      * This function redirects the client. This is done by issuing
  217.      * a "Location" header and exiting if wanted.  If you set $rfc2616 to true
  218.      * HTTP will output a hypertext note with the location of the redirect.
  219.      * 
  220.      * @static 
  221.      * @access  public 
  222.      * @return  mixed   Returns true on succes (or exits) or false if headers
  223.      *                  have already been sent.
  224.      * @param   string  $url URL where the redirect should go to.
  225.      * @param   bool    $exit Whether to exit immediately after redirection.
  226.      * @param   bool    $rfc2616 Wheter to output a hypertext note where we're
  227.      *                  redirecting to (Redirecting to <a href="...">...</a>.)
  228.      */
  229.     function redirect($url, $exit = true, $rfc2616 = false)
  230.     {
  231.         if (headers_sent()) {
  232.             return false;
  233.         }
  234.         
  235.         $url = HTTP::absoluteURI($url);
  236.         header('Location: '. $url);
  237.         
  238.         if (    $rfc2616 && isset($_SERVER['REQUEST_METHOD']) &&
  239.                 $_SERVER['REQUEST_METHOD'] != 'HEAD') {
  240.             printf('Redirecting to: <a href="%s">%s</a>.', $url, $url);
  241.         }
  242.         if ($exit) {
  243.             exit;
  244.         }
  245.         return true;
  246.     }
  247.  
  248.     /**
  249.      * Absolute URI
  250.      * 
  251.      * This function returns the absolute URI for the partial URL passed.
  252.      * The current scheme (HTTP/HTTPS), host server, port, current script
  253.      * location are used if necessary to resolve any relative URLs.
  254.      * 
  255.      * Offsets potentially created by PATH_INFO are taken care of to resolve
  256.      * relative URLs to the current script.
  257.      * 
  258.      * You can choose a new protocol while resolving the URI.  This is 
  259.      * particularly useful when redirecting a web browser using relative URIs 
  260.      * and to switch from HTTP to HTTPS, or vice-versa, at the same time.
  261.      * 
  262.      * @author  Philippe Jausions <Philippe.Jausions@11abacus.com> 
  263.      * @static 
  264.      * @access  public 
  265.      * @return  string  The absolute URI.
  266.      * @param   string  $url Absolute or relative URI the redirect should go to.
  267.      * @param   string  $protocol Protocol to use when redirecting URIs.
  268.      * @param   integer $port A new port number.
  269.      */
  270.     function absoluteURI($url = null, $protocol = null, $port = null)
  271.     {
  272.         // filter CR/LF
  273.         $url = str_replace(array("\r", "\n"), ' ', $url);
  274.         
  275.         // Mess around with already absolute URIs
  276.         if (preg_match('!^([a-z0-9]+)://!i', $url)) {
  277.             if (empty($protocol) && empty($port)) {
  278.                 return $url;
  279.             }
  280.             if (!empty($protocol)) {
  281.                 $url = $protocol .':'. end($array = explode(':', $url, 2));
  282.             }
  283.             if (!empty($port)) {
  284.                 $url = preg_replace('!^(([a-z0-9]+)://[^/:]+)(:[\d]+)?!i', 
  285.                     '\1:'. $port, $url);
  286.             }
  287.             return $url;
  288.         }
  289.             
  290.         $host = 'localhost';
  291.         if (!empty($_SERVER['HTTP_HOST'])) {
  292.             list($host) = explode(':', $_SERVER['HTTP_HOST']);
  293.         } elseif (!empty($_SERVER['SERVER_NAME'])) {
  294.             list($host) = explode(':', $_SERVER['SERVER_NAME']);
  295.         }
  296.  
  297.         if (empty($protocol)) {
  298.             if (isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on')) {
  299.                 $protocol = 'https';
  300.             } else {
  301.                 $protocol = 'http';
  302.             }
  303.             if (!isset($port) || $port != intval($port)) {
  304.                 $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80;
  305.             }
  306.         }
  307.         
  308.         if ($protocol == 'http' && $port == 80) {
  309.             unset($port);
  310.         }
  311.         if ($protocol == 'https' && $port == 443) {
  312.             unset($port);
  313.         }
  314.  
  315.         $server = $protocol .'://'. $host . (isset($port) ? ':'. $port : '');
  316.         
  317.         if (!strlen($url)) {
  318.             $url = isset($_SERVER['REQUEST_URI']) ? 
  319.                 $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF'];
  320.         }
  321.         
  322.         if ($url{0} == '/') {
  323.             return $server . $url;
  324.         }
  325.         
  326.         // Check for PATH_INFO
  327.         if (isset($_SERVER['PATH_INFO']) && strlen($_SERVER['PATH_INFO']) && 
  328.                 $_SERVER['PHP_SELF'] != $_SERVER['PATH_INFO']) {
  329.             $path = dirname(substr($_SERVER['PHP_SELF'], 0, -strlen($_SERVER['PATH_INFO'])));
  330.         } else {
  331.             $path = dirname($_SERVER['PHP_SELF']);
  332.         }
  333.         
  334.         if (substr($path = strtr($path, '\\', '/'), -1) != '/') {
  335.             $path .= '/';
  336.         }
  337.         
  338.         return $server . $path . $url;
  339.     }
  340.  
  341.     /**
  342.      * Raise Error
  343.      * 
  344.      * Lazy raising of PEAR_Errors.
  345.      * 
  346.      * @static 
  347.      * @access  protected 
  348.      * @return  object PEAR_Error
  349.      * @param   mixed   $error 
  350.      * @param   int     $code 
  351.      */
  352.     function raiseError($error = null, $code = null)
  353.     {
  354.         require_once 'PEAR.php';
  355.         return PEAR::raiseError($error, $code);
  356.     }
  357. }
  358.  
  359. ?>
  360.